"""
ORM Repository 基类
提供通用的CRUD操作方法
遵循开发规范，使用泛型确保类型安全
"""
from typing import TypeVar, Generic, List, Optional, Type, Any
from sqlalchemy.orm import Session
from database.connection import get_sync_session
from utils.logger import app_logger

T = TypeVar('T')  # ORM模型类型


class ORMBaseRepository(Generic[T]):
    """
    ORM Repository 基类（提供通用 CRUD 方法）

    使用示例:
        class ORMUserRepository(ORMBaseRepository[UserORM]):
            def __init__(self):
                super().__init__(UserORM)
    """

    def __init__(self, model_class: Type[T]):
        """
        初始化Repository

        Args:
            model_class: ORM模型类
        """
        self.model_class = model_class

    # ==================== 查询方法 ====================

    def get_all_models(self) -> List[T]:
        """获取所有记录"""
        try:
            with get_sync_session() as session:
                return session.query(self.model_class).all()
        except Exception as e:
            app_logger.error(f"查询所有记录失败: {e}", exc_info=True)
            raise

    def get_model_by_id(self, model_id: int) -> Optional[T]:
        """
        根据ID获取记录

        Args:
            model_id: 记录ID

        Returns:
            模型对象，不存在返回None
        """
        try:
            with get_sync_session() as session:
                return session.query(self.model_class).filter(
                    self.model_class.id == model_id
                ).first()
        except Exception as e:
            app_logger.error(f"根据ID查询失败: {model_id}, 错误: {e}", exc_info=True)
            raise

    def find_models(
        self,
        where_conditions: Optional[List[Any]] = None,
        order_by: Optional[List[Any]] = None,
        limit: Optional[int] = None,
        offset: Optional[int] = None
    ) -> List[T]:
        """
        条件查询

        Args:
            where_conditions: WHERE条件列表 [User.age > 18, User.is_active == True]
            order_by: 排序条件列表 [User.created_at.desc()]
            limit: 限制返回数量
            offset: 偏移量

        Returns:
            模型列表
        """
        try:
            with get_sync_session() as session:
                query = session.query(self.model_class)

                # 添加WHERE条件
                if where_conditions:
                    for condition in where_conditions:
                        query = query.filter(condition)

                # 添加排序
                if order_by:
                    for order in order_by:
                        query = query.order_by(order)

                # 分页
                if offset is not None:
                    query = query.offset(offset)
                if limit is not None:
                    query = query.limit(limit)

                return query.all()

        except Exception as e:
            app_logger.error(f"条件查询失败: {e}", exc_info=True)
            raise

    def count_models(self, where_conditions: Optional[List[Any]] = None) -> int:
        """
        统计数量

        Args:
            where_conditions: WHERE条件列表

        Returns:
            记录数量
        """
        try:
            with get_sync_session() as session:
                query = session.query(self.model_class)

                if where_conditions:
                    for condition in where_conditions:
                        query = query.filter(condition)

                return query.count()

        except Exception as e:
            app_logger.error(f"统计数量失败: {e}", exc_info=True)
            raise

    # ==================== 写入方法 ====================

    def insert_model(self, model: T) -> int:
        """
        插入单条记录

        Args:
            model: ORM模型对象

        Returns:
            插入记录的ID
        """
        try:
            with get_sync_session() as session:
                session.add(model)
                session.flush()  # 刷新以获取ID
                model_id = model.id
                session.commit()
                app_logger.info(f"插入记录成功: ID={model_id}")
                return model_id

        except Exception as e:
            app_logger.error(f"插入记录失败: {e}", exc_info=True)
            raise

    def batch_insert_models(self, models: List[T]) -> int:
        """
        批量插入记录

        Args:
            models: ORM模型对象列表

        Returns:
            插入数量
        """
        try:
            if not models:
                return 0

            with get_sync_session() as session:
                session.bulk_save_objects(models)
                session.commit()
                count = len(models)
                app_logger.info(f"批量插入成功: 数量={count}")
                return count

        except Exception as e:
            app_logger.error(f"批量插入失败: {e}", exc_info=True)
            raise

    def update_model(self, model: T) -> bool:
        """
        更新单条记录

        Args:
            model: ORM模型对象（必须有ID）

        Returns:
            是否更新成功
        """
        try:
            with get_sync_session() as session:
                session.merge(model)
                session.commit()
                app_logger.info(f"更新记录成功: ID={model.id}")
                return True

        except Exception as e:
            app_logger.error(f"更新记录失败: {e}", exc_info=True)
            raise

    def batch_update_models(self, models: List[T]) -> int:
        """
        批量更新记录

        Args:
            models: ORM模型对象列表

        Returns:
            更新数量
        """
        try:
            if not models:
                return 0

            with get_sync_session() as session:
                for model in models:
                    session.merge(model)
                session.commit()
                count = len(models)
                app_logger.info(f"批量更新成功: 数量={count}")
                return count

        except Exception as e:
            app_logger.error(f"批量更新失败: {e}", exc_info=True)
            raise

    def delete_by_id(self, model_id: int) -> bool:
        """
        根据ID删除记录

        Args:
            model_id: 记录ID

        Returns:
            是否删除成功
        """
        try:
            with get_sync_session() as session:
                model = session.query(self.model_class).filter(
                    self.model_class.id == model_id
                ).first()

                if model:
                    session.delete(model)
                    session.commit()
                    app_logger.info(f"删除记录成功: ID={model_id}")
                    return True
                else:
                    app_logger.warning(f"删除失败：记录不存在 ID={model_id}")
                    return False

        except Exception as e:
            app_logger.error(f"删除记录失败: {model_id}, 错误: {e}", exc_info=True)
            raise

    def batch_delete_by_ids(self, ids: List[int]) -> int:
        """
        批量删除记录

        Args:
            ids: ID列表

        Returns:
            删除数量
        """
        try:
            if not ids:
                return 0

            with get_sync_session() as session:
                count = session.query(self.model_class).filter(
                    self.model_class.id.in_(ids)
                ).delete(synchronize_session=False)
                session.commit()
                app_logger.info(f"批量删除成功: 数量={count}")
                return count

        except Exception as e:
            app_logger.error(f"批量删除失败: {e}", exc_info=True)
            raise
